package controller;

import java.math.BigInteger;
import java.util.Random;

import metier.Cle;
import metier.Tuple;


public class ControllerCle {

	private BigInteger m_p ;
	private BigInteger m_q ;
	public BigInteger m_n ;
	public BigInteger m_e ;
	private Cle cle_pub ;
	private Cle cle_priv;
	private Tuple tuple ;
	
	public void generateKey(){

		Random rnd = new Random();

		m_p = BigInteger.probablePrime(32,rnd);
		m_q = BigInteger.probablePrime(32,rnd);
		
		//p et q doivent être différent
		while(m_p.equals(m_q)){
			m_q = BigInteger.probablePrime(32,rnd);
		}

		
		m_n = m_p.multiply(m_q);

		BigInteger q_tmp = m_q ;
		BigInteger p_tmp = m_p ;
		BigInteger un = new BigInteger("1");

		q_tmp = q_tmp.subtract(un);
		p_tmp = p_tmp.subtract(un);

		BigInteger m_m = q_tmp.multiply(p_tmp);

		cle_pub = calculClePublique(m_m);
		cle_priv = calculClePrive(m_m);

	}

	/**
	 * Calcul de la clé publique
	 * On genère des entiers de manières aléatoire
	 * jusqu'a en avoir un qui soit premier avec m_m
	 * @param m_m
	 * @return Cle_pub
	 */
	private Cle calculClePublique(BigInteger m_m){
		BigInteger un = new BigInteger("1");
		m_e = generateInteger() ; 

		BigInteger est_prim = m_m.gcd(new BigInteger(m_e+""));

		while(!est_prim.equals(un) && !m_e.equals(new BigInteger("1"))){
			m_e = generateInteger();
			est_prim = m_m.gcd(new BigInteger(m_e+""));
		}

		return new Cle(m_n,m_e);
	}

	/**
	 * On calcul la clé prive grace à l'algorithme d'euclide
	 * @return Cle_prive
	 */
	private Cle calculClePrive(BigInteger m){
		Euclide euc = new Euclide();
		BigInteger e = new BigInteger(""+m_e);
		BigInteger u = euc.algorihtmeEuclideEtendu(e,m);
		u = euc.normalize(u, m);
		BigInteger m_u = u;
		return new Cle(m_n,m_u);
	}

	private BigInteger generateInteger()
	{
		int integer = (int) (Math.random()*1000);
		if (integer % 2 == 0)
		{
			if ( integer < Integer.MAX_VALUE)
				integer += 1;
			else
				integer -= 1;
		}
		return BigInteger.valueOf(integer);
	}

	public Cle getCle_pub() {
		return cle_pub;
	}
	
	//TODO supprimer le get 
	public Cle getCle_priv() {
		return cle_priv;
	}


	public void setCle_pub(Cle cle_pub) {
		this.cle_pub = cle_pub;
	}
	
	public String dechiffrement(String[] tab){
		tuple = new Tuple(tab);
		tuple.dechiffrement(this.cle_priv);
		
		return tuple.toStringMessage();
	}
	
	public String[] chiffrement(String message,Cle publique){
		tuple = new Tuple(message);
		tuple.makeTuple();
		
		tuple.chiffrement(publique);
		
		
		return tuple.getTabString() ;
	}
	
}
